<?php
namespace PsiFramework\Classes\Actions;

import("Classes.Actions.ActionsInterface.IAction");
import("Classes.Exceptions.SecurityException");
import("Classes.Util.HTTP.AuthenticationManager");
import("Classes.Util.HTTP.Request");
import("Classes.Util.HTTP.RedirectionManager");
import("Classes.Util.Log.Logger");
import("Classes.Util.Manager.ApplicationManager");
import("Classes.Util.Parameters.Action.ActionParameters");
import("Classes.Util.Security.Manager.SecurityManager");
import("Classes.Util.UI.Response");
import("Classes.Util.UI.TemplateManager");
import("Classes.Util.UI.ModuleManager");

use \PsiFramework\Classes\Actions\ActionsInterface\IAction;
use \PsiFramework\Classes\Exceptions\SecurityException;
use \PsiFramework\Classes\Factory\ActionFactory;
use \PsiFramework\Classes\Factory\DAOFactory;
use \PsiFramework\Classes\Util\HTTP\AuthenticationManager;
use \PsiFramework\Classes\Util\HTTP\Request;
use \PsiFramework\Classes\Util\HTTP\RedirectionManager;
use \PsiFramework\Classes\Util\Log\Logger;
use \PsiFramework\Classes\Util\Manager\ApplicationManager;
use \PsiFramework\Classes\Util\Parameters\Action\ActionParameters;
use \PsiFramework\Classes\Util\Security\Manager\SecurityManager;
use \PsiFramework\Classes\Util\UI\HTML;
use \PsiFramework\Classes\Util\UI\Response;
use \PsiFramework\Classes\Util\UI\TemplateManager;
use \PsiFramework\Classes\Util\UI\ModuleManager;

/**
 * PsiFramework
 * Php Simple Framework
 *
 * @author Rémi San
 * @version beta
 */

/**
 * Classe abstraite d'actions
 *
 * @package Actions
 */
abstract class AbstractAction implements IAction
{

    protected /*Request*/               $_request ;
    protected /*Response*/              $_response ;
    protected /*AuthenticationManager*/ $_authenticationManager ;
    protected /*RedirectionManager*/    $_redirectionManager ;
    protected /*TemplateManager*/       $_templateManager ;
    protected /*ActionParameters*/      $_actionParameters ;
    protected /*string*/                $_template ;

    /**
     * 
     * @var IUser
     */
    protected /*IUser*/                 $_user ;
    
    protected /*Logger*/                $_logger ;

    protected /*string*/                $_objectType ;
    protected /*int*/                   $_id ;

    /**
     * AbstractAction constructor
     */
    public function __construct(ActionParameters $actionParameters=null)
    {

        $this->_authenticationManager = AuthenticationManager::getInstance();
        $this->_response = new Response();
        $this->_response->setAttribute(
            'authenticated_user',
            $this->_authenticationManager->getAuthenticatedUser()
        );
        $this->_request = Request::getInstance();
        $this->_templateManager = TemplateManager::getInstance();
        $this->_redirectionManager = RedirectionManager::getInstance();
        $this->_actionParameters = $actionParameters ;
        if (!is_null($actionParameters)) {
            $this->_template = $this->_actionParameters->getTemplate();
        } else {
            $this->_template = 'layout' ;
        }

        $this->_logger = new Logger(get_class($this));

        $this->_objectType = null ;
        $this->_id = null ;
        
        $user = AuthenticationManager::getInstance()->getAuthenticatedUser();
        
        if (!is_null($user)) {
        	$userDao = DAOFactory::getDAO('User');
        	$this->_user = $userDao->retrieveByPk($user->getId(), false, false);
        } else {
        	$this->_user = null ;
        }
    }

    public function getTemplate()
    {
        return $this->_template ;
    }

    public function setTemplate(/*string*/ $template)
    {
        $this->_template = $template ;
    }
    
    public function setResponse($response)
    {
        $this->_response = $response ;
    }

    /**
     * The main function of the method which is called every time
     * an action is created by the front controller.
     *
     * @param    Object    $object
     */
    public function execute(/*string[]*/ $vars=null)
    {
        $this->_objectType = $this->_request->getParameter('type');
        $this->_id = $this->_request->getParameter('id');

        if (!isNullOrEmptyString($this->_response->getAttribute('id'))) {
            $this->_id = $this->_response->getAttribute('id');
        }
        
        $this->_response->setAttribute('objectType', $this->_objectType);
        $this->_response->setAttribute('id', $this->_id);
        $this->_response->setAttribute('url', $this->_request->getRequestURI());
        $this->_response->setAttribute('calledAction', $this->_request->getParameter('action'));
        
        ModuleManager::getInstance()->addModule('Debug', $this->_response);
    }

    public function findForward(
        /*string*/ $name,
        /*string*/ $redirect=null,
        /*bool*/ $append=false
    )
    {
        $redirection = $this->_request->getParameter('redirect');
        if (!isNullOrEmptyString($redirection) && isNullOrEmptyString($redirect)) {
            $this->_redirectionManager->redirect($redirection);
        	exit;
        }
        
        $popup = $this->_request->getParameter('popup');
        if (!isNullOrEmptyString($popup)) {
            $this->_templateManager->addLitteralScript(
                '
                $(document).ready(function(){
                    psiPopup("'.$popup.'");    
                });
                '
            );
        }
        
        if (is_null($this->_actionParameters)) {
            throw new \Exception("No forwarding configuration !");
        }
        
        $forward = $this->_actionParameters->getForward($name);
        if (!is_null($forward)) {
            if (!isNullOrEmptyString($forward->getPage())) {
                $this->_templateManager->addTemplate(
                    $forward->getPage(),
                    $this->_response
                );
            } else if (!isNullOrEmptyString($forward->getRedirectionAction())) {
                $actionFactory = ActionFactory::getInstance();
                $action = $actionFactory->getAction($forward->getRedirectionAction());
                if (!is_null($action)) {
                    $action->setResponse($this->_response);
                    $this->setTemplate($action->getTemplate());
                    $action->execute();
                }
            } else if (!isNullOrEmptyString($forward->getRedirectToLink())) {
                //we get the redirect parameter (Profile by default)
                if (isNullOrEmptyString($redirect)) {
                    $redirect = $forward->getRedirectToLink();
                } else if ($append) {
                    if (startsWith($redirect, '&') === false) {
                        $redirect = '&'.$redirect;
                    }
                    $redirect = $forward->getRedirectToLink().$redirect ;
                }
                
                $this->_redirectionManager->redirect(
                    HTML::linkHref($redirect, false)
                );
                exit;
            }
        }
    }
    
    public function getResponse()
    {
        return $this->_response;
    }
    
    /**
     * The default method which throws an exception
     * if an unknown function is called
     *
     * @param string $method The name of the method
     * @param array  $args   The array of arguments
     *
     * @return void
     *
     * @throws \Exception
     */
    public function __call($method, $args)
    {
    	throw new \Exception(
			"The method '".$method."' doesn't exist for ".
			"class '".get_class($this)."'"
    	);
    }
}
